/**
 *   FUSE-J: Java bindings for FUSE (Filesystem in Userspace by Miklos Szeredi (mszeredi@inf.bme.hu))
 *
 *   Copyright (C) 2003 Peter Levart (peter@select-tech.si)
 *
 *   This program can be distributed under the terms of the GNU LGPL.
 *   See the file COPYING.LIB
 */
package fuse;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

/**
 * This is an adapter that implements fuse.FuseFS byte level API and delegates
 * to the fuse.Filesystem String level API. You specify the encoding to be used
 * for file names and paths.
 */
public class FilesystemToFuseFSAdapter implements FuseFS
{
   private Filesystem fs2;
   private Charset cs;

   public FilesystemToFuseFSAdapter(Filesystem fs2)
   {
      this(fs2, System.getProperty("file.encoding", "UTF-8"));
   }

   public FilesystemToFuseFSAdapter(Filesystem fs2, String encoding)
   {
      this(fs2, Charset.forName(encoding));
   }

   public FilesystemToFuseFSAdapter(Filesystem fs2, Charset cs)
   {
      this.fs2 = fs2;
      this.cs = cs;
   }

   //
   // FuseFS implementation

   public FuseStat getattr(ByteBuffer path) throws FuseException
   {
      return fs2.getattr(cs.decode(path).toString());
   }

   public void readlink(ByteBuffer path, ByteBuffer link) throws FuseException
   {
      cs.newEncoder().encode(CharBuffer.wrap(fs2.readlink(cs.decode(path).toString())), link, true);
   }

   public FuseFSDirEnt[] getdir(ByteBuffer path) throws FuseException
   {
      FuseDirEnt[] ents2 = fs2.getdir(cs.decode(path).toString());
      FuseFSDirEnt[] ents = new FuseFSDirEnt[ents2.length];

      for (int i = 0; i < ents.length; i++)
      {
         FuseDirEnt dirEntry = ents2[i];
         FuseFSDirEnt ent = new FuseFSDirEnt();
         ents[i] = ent;
         ByteBuffer bb = cs.encode(dirEntry.name);
         ent.name = new byte[bb.remaining()];
         bb.get(ent.name);
         ent.inode = dirEntry.inode;
      }

      return ents;
   }

   public void mknod(ByteBuffer path, int mode, int rdev) throws FuseException
   {
      fs2.mknod(cs.decode(path).toString(), mode, rdev);
   }

   public void mkdir(ByteBuffer path, int mode) throws FuseException
   {
      fs2.mkdir(cs.decode(path).toString(), mode);
   }

   public void unlink(ByteBuffer path) throws FuseException
   {
      fs2.unlink(cs.decode(path).toString());
   }

   public void rmdir(ByteBuffer path) throws FuseException
   {
      fs2.rmdir(cs.decode(path).toString());
   }

   public void symlink(ByteBuffer from, ByteBuffer to) throws FuseException
   {
      fs2.symlink(cs.decode(from).toString(), cs.decode(to).toString());
   }

   public void rename(ByteBuffer from, ByteBuffer to) throws FuseException
   {
      fs2.rename(cs.decode(from).toString(), cs.decode(to).toString());
   }

   public void link(ByteBuffer from, ByteBuffer to) throws FuseException
   {
      fs2.link(cs.decode(from).toString(), cs.decode(to).toString());
   }

   public void chmod(ByteBuffer path, int mode) throws FuseException
   {
      fs2.chmod(cs.decode(path).toString(), mode);
   }

   public void chown(ByteBuffer path, int uid, int gid) throws FuseException
   {
      fs2.chown(cs.decode(path).toString(), uid, gid);
   }

   public void truncate(ByteBuffer path, long size) throws FuseException
   {
      fs2.truncate(cs.decode(path).toString(), size);
   }

   public void utime(ByteBuffer path, int atime, int mtime) throws FuseException
   {
      fs2.utime(cs.decode(path).toString(), atime, mtime);
   }

   public FuseStatfs statfs() throws FuseException
   {
      return fs2.statfs();
   }

   public long open(ByteBuffer path, int flags) throws FuseException
   {
      return fs2.open(cs.decode(path).toString(), flags);
   }

   public void read(ByteBuffer path, long fh, ByteBuffer buf, long offset) throws FuseException
   {
      fs2.read(cs.decode(path).toString(), fh, buf, offset);
   }

   public void write(ByteBuffer path, long fh, boolean isWritepage, ByteBuffer buf, long offset) throws FuseException
   {
      fs2.write(cs.decode(path).toString(), fh, isWritepage, buf, offset);
   }

   public void flush(ByteBuffer path, long fh) throws FuseException
   {
      fs2.flush(cs.decode(path).toString(), fh);
   }

   public void release(ByteBuffer path, long fh, int flags) throws FuseException
   {
      fs2.release(cs.decode(path).toString(), fh, flags);
   }

   public void fsync(ByteBuffer path, long fh, boolean isDatasync) throws FuseException
   {
      fs2.fsync(cs.decode(path).toString(), fh, isDatasync);
   }
}
